import { CacheService } from '@app/cache';
import { ConfigureService } from '@app/configure';
import { Device } from '@app/db/entities/Device';
import { OrderPowerData, OrderPowerDataDocument } from '@app/mongodb/schemas/orderPowerData';
import { DeviceData, DeviceDataDocument } from '@app/mongodb/schemas/deviceData';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { InjectRepository } from '@nestjs/typeorm';
import { MqttClientService } from 'apps/mqtt-client/src/mqtt-client.service';
import { Model } from 'mongoose';
import { Repository } from 'typeorm';
import { PrivateChargePowerData, PrivateChargePowerDataDocument } from '@app/mongodb/schemas/privateChargePowerData';
import { OtaService } from './ota/ota.service';

@Injectable()
export class DeviceDataProcessingService {
  private devicePortChargingKeyReg:string
  private readonly deviceIdPortToOrderIdReg:string //设备id和端口号对应的订单id


  constructor(
    private mqttClient:MqttClientService,
    private config:ConfigureService,
    private cache:CacheService,
    private otaService:OtaService,

    @InjectRepository(Device) protected repository:Repository<Device>,

    @InjectModel(DeviceData.name) public readonly deviceData: Model<DeviceDataDocument>,
    @InjectModel(OrderPowerData.name) public readonly orderPowerData: Model<OrderPowerDataDocument>,
    @InjectModel(PrivateChargePowerData.name) public readonly privateChargePowerData: Model<PrivateChargePowerDataDocument>,
  ){
    this.devicePortChargingKeyReg = config.get('devicePortChargingKeyReg')
    this.deviceIdPortToOrderIdReg = config.get('deviceIdPortToOrderIdReg')
  }

  start() {
    const mqtt = this.mqttClient.client("mqtt://127.0.0.1:" + this.config.get('mqtt.port'))
    mqtt.on('connect', () => {
      mqtt.subscribe('/#')
    })

    mqtt.on('message', (topic, message) => {
    
      try {
        const _msg = message.toString()
        const msg = JSON.parse(_msg)
        //console.log(msg)
        if(!msg) return

        if(topic.indexOf('/as/mqtt/status') == 0) { //设备状态
          const deviceId = Number(msg.deviceName)

          let updateData:{[key in keyof Device]? : Device[key]} = {}
          let time = Math.floor((new Date(msg.time)).getTime() / 1000)
          if(msg.status == 'online') {
            updateData.connectStatus = 1
            updateData.onlineTime = time
          }else {
            updateData.connectStatus = 0
            updateData.offlineTime = time
          }

          this.repository.update({id : deviceId}, updateData)
          return
        }

        

        if('type' in msg) {
          const type = msg.type

          if(type == 10) { //服务器主动查询设备充电状态，设备回复
            this.type10(msg)
            return
          }

          if(type == 12) { //周期上报
            this.type12(msg)
            return
          }

          if(type == 22) { //远程升级
            this.cache.client.lpush(this.otaService.resListKey, _msg)
          }
          

        }else {
          
        }

      } catch (error) {
        
      }
    })

    mqtt.on('error', () => {
      console.log('mqtt 链接失败')
    })
  }

  type10(msg) {
    const deviceId = String(Number(msg.id))
    for(let i = 1; true; i ++) {
      const key = 'c' + i
      if(!msg[key]) break
      this.cache.set(this.devicePortChargingKeyReg.replace(/\?/, deviceId).replace(/\?/, String(i)), msg[key], 20)
    }
  }

  type12(msg) {
    try {
      const m = msg.m.split('|')
      const status:number[] = m[2].split('')
      const portStatus:any[] = []
      const portData:any[] = []
      const deviceId = String(Number(msg.id))
      const time = Math.floor(Date.now() / 1000)

      


      for(let port = 1; port <= status.length; port ++) {
        portStatus.push(Number(status[port - 1]))
        const data = msg['c' + port].split('|')
        portData.push(data)

        //加入到订单功率
        this.cache.get(this.deviceIdPortToOrderIdReg.replace(/\?/, deviceId).replace(/\?/, String(port))).then(id => {
          //console.log('加入到订单功率')
          //console.log(id)
          if(!id) return

          if(id.endsWith('P')) { //私人充电的
            id = id.slice(0, -1)
            this.privateChargePowerData.updateOne({id : Number(id)}, {$push : {data : {t : time, p : data[2], c : data[5], v : data[7]}}}, {upsert : true}).then((a) => {
              //console.log('加入到私人充电功率1')
              //console.log(a)
            })
          }else {
            this.orderPowerData.updateOne({orderId : Number(id)}, {$push : {data : {t : time, p : data[2], c : data[5], v : data[7]}}}, {upsert : true}).then((a) => {
              //console.log('加入到订单功率1')
              //console.log(a)
            })
          }
          

          
        })
      }

      this.repository.update({id : Number(msg.id)}, {portStatus, portData, connectStatus : 1})

      
    } catch (error) {
      
    }
  }

}
